#include <windows.h>
#include "Console.h"
#include "StdHeader.h"


void TestCpp();

LRESULT CALLBACK MsgProc(HWND hWnd,	UINT uMsg,	WPARAM wParam,	LPARAM lParam	)
{
	switch( uMsg )
	{
	case WM_DESTROY:
		
		PostQuitMessage( 0 );
		return 0;

	case WM_PAINT:
		
		ValidateRect( hWnd, NULL );
		return 0;
	}

	return DefWindowProc( hWnd, uMsg, wParam, lParam );
}

int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nShowCmd )
{
	// Register the window class
	WNDCLASSEX wc =
	{
		sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,
		GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
		"Game", NULL
	};
	RegisterClassEx( &wc );

	// Create the application's window
	HWND hWnd = CreateWindow( "Game", "Game TItle",
		WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
		NULL, NULL, wc.hInstance, NULL );

	ShowWindow( hWnd, SW_HIDE );
	UpdateWindow( hWnd );

	

	Console console;
	console.ShowConsole();

	TestCpp();
	// Enter the message loop
	MSG msg;
	while( GetMessage( &msg, NULL, 0, 0 ) )
	{
		TranslateMessage( &msg );
		DispatchMessage( &msg );
	}

	console.CloseConsole();
	return 0;
}



#include "RefCount.h"
#include "Rtti.h"
#include "memory.h"
// class Test : public GBase::MemObj
// {
// 	G_IMPLEMENT_REFCOUNT_FAST
// class Test : public GBase::RefCountObj
// {
// public:
// 	Test()
// 	{
// 		//std::cout << "Test" << std::endl;
// 	};
// 
// 	void Foo()
// 	{
// 		std::cout << "Test::Foo" << std::endl;
// 	}
// };
//G_DECLARE_SMART_POINTER(Test)


class BaseClass:public GBase::MemObj
{
	G_DeclareRootRTTI(BaseClass)

public:
	BaseClass(){}
	virtual ~BaseClass()
	{
		std::cout << "~BaseClass()" << std::endl;
	}

	void Foo()
	{
		std::cout << "BaseClass::Foo" << std::endl;
	}
};
G_ImplementRootRTTI(BaseClass)

class BaseClass2:public GBase::MemObj
{
public:
	void Foo()
	{
		std::cout << "BaseClass2::Foo" << std::endl;
	}
};

class DeriveClass : public BaseClass, public BaseClass2
{
	G_DeclareDeriveRTTI
public:
	~DeriveClass()
	{
		std::cout << "~DeriveClass()" << std::endl;
	}
};


class BaseVTable
{
public:
	virtual void Foo(){std::cout << "Foo" << std::endl;}
// 	virtual void Goo(){std::cout << "Goo" << std::endl;}
// 	virtual void Hoo(){std::cout << "Hoo" << std::endl;}

public:
	int val;
};

class ConstA;

class ConstA
{
public:
	ConstA()
	{
		m_val = 0;
	}

	ConstA(ConstA& other)
	{
		std::cout << "ConstA(ConstA& other)" << std::endl;
		m_val = 0;
	}

	~ConstA()
	{

	}

	const ConstA& GetObject() 
	{
		m_a = (ConstA*)G_NEW_T(ConstA);
		return *m_a;
	}

	ConstA& operator=(ConstA &other)
	{
		std::cout << "ConstA& operator=(ConstA &other)" << std::endl;
		return *this;
	}

private:
	mutable ConstA *m_a;

public:
	int m_val;
};

G_ImplementDeriveRTTI(DeriveClass, BaseClass)

void TestCpp()
{
	BaseClass *pBase = G_NEW BaseClass();
	DeriveClass *pDerive = G_NEW DeriveClass;
	
#define TestBool(con) con ? "true" : "false"
// 	{
// 		GBase::String strBool = TestBool(G_IsExactKindOf(pDerive, DeriveClass));
// 		//GBase::String strBool = TestBool( G_IsKindOf(pDerive, BaseClass) );
// 		BaseClass *pClass = G_DynamicCast(pDerive, BaseClass);
// 		std::cout << pClass->GetClassName() << std::endl;
// 	}
	
	//pDerive->BaseClass2::Foo();
	using namespace std;
	ConstA A;
	ConstA B = A;
	ConstA C;
	C = A;
	
	//refA.m_val = 10;
	//refA.m_val = 10;
// 	BaseVTable bvTable ;
// 	typedef void (*pFun)();
// 	pFun f ;
// 
// 	int **pv = (int**)(&bvTable);
// 	f = (pFun)pv[0][2];
// 	f();
// 	cout << f  << " " << &bvTable << endl;

// 	BaseVTable bvTable;
// 	int *val = (int*)&bvTable;
// 	*val = 1;
// 	cout << bvTable.val << endl;

// 	typedef GBase::vector<int>::type IntVector;
// 	typedef GBase::vector<int>::iterator IntIterator;
// 	IntVector Varray;
// 	Varray[1] = 10;
// 	Varray[3] = 50;
// 	Varray[80] = 100;


	//for(IntIterator i = Varray.begin(); i != Varray.end(); i++)
	{
		//std::cout << *i << std::endl;
		//cout << Varray.size() << endl;
	}

// 	{
// 		typedef GBase::SmartPointer<Test> TestSmartPointer;
// 		TestSmartPointer spTest;
// 		Test *p = G_NEW Test();
// 		spTest = p;
// 
// 		TestSmartPointer spTest2(new Test);
// 		spTest2->Foo();
// 		GBase::String strBool = spTest == spTest2? "true" : "false";
// 		std::cout << strBool << std::endl;
// 	}
// 
// 	{
// 		TestPtr spTest(new Test);
// 		spTest->Foo();
// 	}
	

	//int*p = G_NEW_ARRAY_T(int, 10);
// 	Test *p = G_NEW_ARRAY_T(Test, 10);
// 	G_DELETE_ARRAY_T(Test, 10, p);

// 	int *c = G_NEW_T(int);
// 	G_DELETE_T(int, c);
		//int *a = G_ALLOC(int, 10);
// 	int *a = new int;
// 	a->~int();
	GBase::AllocTracker::Get().Report();
//    	Test *p = G_NEW Test();
//   	GBase::AllocTracker::Get().Report();
//  
//  	G_DELETE p;
//  	GBase::AllocTracker::Get().Report();
// 
//  	Test *pArr = G_NEW Test[10];
//  	G_DELETE []pArr;
// 	GBase::AllocTracker::Get().Report();
// 
// 	{
// 		int N = 10;
// 		char *buf=new char[N*sizeof(Test)+sizeof(int)]; 
// 		Test *p = new(buf)Test;
// 	}
	

	
}